/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.repository.dbcolumninfo.repoproccessor;

import com.inspur.edp.cef.api.repository.INestedRepository;
import com.inspur.edp.cef.api.repository.readerWriter.ICefReader;
import com.inspur.edp.cef.entity.entity.AssoInfoBase;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.repository.adaptor.EntityRelationalAdaptor;
import com.inspur.edp.cef.repository.adaptoritem.BaseAdaptorItem;
import com.inspur.edp.cef.repository.adaptoritem.dbprocessor.DbProcessor;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfo;
import com.inspur.edp.cef.repository.readerwriter.CefMappingReader;
import com.inspur.edp.cef.repository.repo.BaseRootRepository;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.AssocationPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.DataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.RefDataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.SimpleAssoUdtPropertyInfo;
import com.inspur.edp.udt.entity.ISimpleUdtData;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class SimpleAssoUdtRepoProcessor extends SimpleUdtRepoProcessor {

  @Override
  public  final Object readProperty(DbColumnInfo dbColumnInfo, DbProcessor dbProcessor,
      BaseAdaptorItem adaptorItem, ICefReader reader) {

    SimpleAssoUdtPropertyInfo simpleAssoUdtPropertyInfo= (SimpleAssoUdtPropertyInfo) dbColumnInfo.getDataTypePropertyInfo().getObjectInfo();
    if(simpleAssoUdtPropertyInfo.hasEnrichedProps()==false) {
      CefMappingReader mappingReader = new CefMappingReader(simpleAssoUdtPropertyInfo.getAssoInfo().getAssDbMapping(), reader);
      for(Map.Entry<String,DataTypePropertyInfo> refEntity:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getRefPropInfos().entrySet())
      {
        if(refEntity.getValue().getObjectInfo() instanceof AssocationPropertyInfo)
        {
          AssocationPropertyInfo assocationPropertyInfo= (AssocationPropertyInfo) refEntity.getValue().getObjectInfo();
          for(Map.Entry<String, DataTypePropertyInfo> refRefEntry:assocationPropertyInfo.getAssociationInfo().getRefPropInfos().entrySet()) {
            simpleAssoUdtPropertyInfo.getAssoInfo().getAssDbMapping().put(simpleAssoUdtPropertyInfo.getUdtConfigId().substring(simpleAssoUdtPropertyInfo.getUdtConfigId().lastIndexOf("." )+ 1) + "_" + refRefEntry.getKey(),dbColumnInfo.getDataTypePropertyInfo().getPropertyName()+"_"+refRefEntry.getKey());
          }
        }
      }
      INestedRepository u1Repos = adaptorItem.getNestedRepo(simpleAssoUdtPropertyInfo.getUdtConfigId());
      return u1Repos.readData(mappingReader);
    }
    else
    {
      CefMappingReader mappingReader = new CefMappingReader(simpleAssoUdtPropertyInfo.getAssoInfo().getAssDbMapping(), reader);
      for(Map.Entry<String,DataTypePropertyInfo> refEntity:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getRefPropInfos().entrySet())
      {
        if(refEntity.getValue().getObjectInfo() instanceof AssocationPropertyInfo)
        {
          AssocationPropertyInfo assocationPropertyInfo= (AssocationPropertyInfo) refEntity.getValue().getObjectInfo();
          for(Map.Entry<String, DataTypePropertyInfo> refRefEntry:assocationPropertyInfo.getAssociationInfo().getRefPropInfos().entrySet()) {
            simpleAssoUdtPropertyInfo.getAssoInfo().getAssDbMapping().put(simpleAssoUdtPropertyInfo.getUdtConfigId().substring(simpleAssoUdtPropertyInfo.getUdtConfigId().lastIndexOf(".") + 1) + "_" + refRefEntry.getKey(),dbColumnInfo.getDataTypePropertyInfo().getPropertyName()+"_"+refRefEntry.getKey());
          }
        }
      }
      INestedRepository u1Repos = adaptorItem.getNestedRepo(simpleAssoUdtPropertyInfo.getUdtConfigId());
      ICefData data= u1Repos.readData(mappingReader);
      try {
        Constructor  constructor =simpleAssoUdtPropertyInfo.getEnrichedAssType().getDeclaredConstructors()[0];
        ISimpleUdtData result = (ISimpleUdtData) constructor.newInstance(data);
        AssoInfoBase value = (AssoInfoBase) result.getValue();
        EntityRelationalAdaptor adapter=((BaseRootRepository)adaptorItem.getAssociation(dbColumnInfo.getColumnName()).getRefRepository()).getEntityDac(simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getNodeCode()).getEntityAdaptor();
          HashMap<String,String> map=new HashMap<>();
          for (Map.Entry<String, DataTypePropertyInfo> item:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getEnrichedRefPropInfos().entrySet())
          {
              RefDataTypePropertyInfo refDataTypePropertyInfo= (RefDataTypePropertyInfo) item.getValue();
              map.put(refDataTypePropertyInfo.getRefPropertyName(),refDataTypePropertyInfo.getPropertyName());

              if(item.getValue().getObjectInfo() instanceof AssocationPropertyInfo)
              {
                AssocationPropertyInfo assocationPropertyInfo= (AssocationPropertyInfo) item.getValue().getObjectInfo();
                for(Map.Entry<String,DataTypePropertyInfo> refItem:assocationPropertyInfo.getAssociationInfo().getRefPropInfos().entrySet())
                {
                  map.put(refItem.getValue().getPropertyName(),dbColumnInfo.getDataTypePropertyInfo().getPropertyName()+"_"+refItem.getValue().getPropertyName());
                }
              }
              else if(item.getValue().getObjectInfo() instanceof SimpleAssoUdtPropertyInfo)
              {
                SimpleAssoUdtPropertyInfo assocationPropertyInfo= (SimpleAssoUdtPropertyInfo) item.getValue().getObjectInfo();
                for(Map.Entry<String,DataTypePropertyInfo> refItem:assocationPropertyInfo.getAssoInfo().getAssociationInfo().getRefPropInfos().entrySet())
                {
                  map.put(refItem.getValue().getPropertyName(),dbColumnInfo.getDataTypePropertyInfo().getPropertyName()+"_"+refItem.getValue().getPropertyName());
                }
              }
          }
        CefMappingReader mappingReader1=new CefMappingReader(map,reader);
        for (Map.Entry<String, DataTypePropertyInfo> item:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getEnrichedRefPropInfos().entrySet())
        {
          RefDataTypePropertyInfo refDataTypePropertyInfo= (RefDataTypePropertyInfo) item.getValue();
          value.setValue(refDataTypePropertyInfo.getPropertyName(),adapter.readProperty(refDataTypePropertyInfo.getRefPropertyName(),mappingReader1));
        }
        return result;
      }  catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      } catch (InstantiationException e) {
        throw new RuntimeException(e);
      } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }
  }

  public  final Object readProperty(DbColumnInfo dbColumnInfo, DbProcessor dbProcessor,
                                    BaseAdaptorItem adaptorItem, ICefReader reader,String refPropertyName)
  {
    SimpleAssoUdtPropertyInfo simpleAssoUdtPropertyInfo= (SimpleAssoUdtPropertyInfo) dbColumnInfo.getDataTypePropertyInfo().getObjectInfo();
//    Constructor  constructor =simpleAssoUdtPropertyInfo.getAssoInfo().getAssoType().getDeclaredConstructors()[0];
    EntityRelationalAdaptor adapter=((BaseRootRepository)adaptorItem.getAssociation(dbColumnInfo.getColumnName()).getRefRepository()).getEntityDac(simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getNodeCode()).getEntityAdaptor();
    HashMap<String,String> map=new HashMap<>();
    for (Map.Entry<String, DataTypePropertyInfo> item:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getEnrichedRefPropInfos().entrySet())
    {
      RefDataTypePropertyInfo refDataTypePropertyInfo= (RefDataTypePropertyInfo) item.getValue();
      map.put(refDataTypePropertyInfo.getRefPropertyName(),refDataTypePropertyInfo.getPropertyName());
    }
    for (Map.Entry<String, DataTypePropertyInfo> item:simpleAssoUdtPropertyInfo.getAssoInfo().getAssociationInfo().getRefPropInfos().entrySet())
    {
      RefDataTypePropertyInfo refDataTypePropertyInfo= (RefDataTypePropertyInfo) item.getValue();
      map.put(refDataTypePropertyInfo.getRefPropertyName(),refDataTypePropertyInfo.getPropertyName());
    }
    CefMappingReader mappingReader1=new CefMappingReader(map,reader);
   return adapter.readProperty(refPropertyName,mappingReader1);
  }
}
